package FlowGraph.StatementInfo;

import java.util.*;
import java.lang.reflect.Constructor;

import antlr.collections.AST;
import antlr.*;

import db.ClassData;
import SymbolTable.*;
import JavaGrammar.TreeScanners.MethodParser;
import util.Util;

//////////////////////////////////////////////////////////////////////////
//// NewStatementInfo
/**

        Guarda informacoes sobre um statement de new.

@author Ivan Jeukens
@version v 0.1 17/06/2002
*/
public class NewStatementInfo {

    public NewStatementInfo(VarDefStatementInfo vardef) {
        _vardef = vardef;
        _constructor = null;
    }

    ///////////////////////////////////////////////////////////////////
    ////                        public methods                     //// 
    
    public Constructor getConstructor() {
        return _constructor;
    }

    /* Metodo similar ao do MethodCallNode */
    public void parse(ClassData dbinfo, SymbolTable ports,
            SymbolTable parameters, SymbolTable variables) {
        AST statement = _vardef.getStatement();

        MethodParser parser = new MethodParser();

        parser.addSymbolTable(variables);
        parser.addSymbolTable(ports);
        parser.addSymbolTable(parameters);
        parser.addSymbolTable(_vardef.getNode().getSymbolTable());

        parser.setClassName(dbinfo.getName());
        parser.setPackage(dbinfo.getPackage());
        parser.setClassInfo(dbinfo);

        try {
            parser.parsemc(statement);
        }
        catch(RecognitionException ex) {
            System.out.println("RecognitionException:");
            System.out.println(ex);
        }

        _parameterTypes = new LinkedList();
        for(int i = 0;i < parser.parameterTypes.size();i++) {
            String s = (String) parser.parameterTypes.get(i);
            _parameterTypes.add(Util.getType(s, dbinfo.getName(), 
                dbinfo.getPackage(), dbinfo.getImports()));
        }
        _typeName = parser.returnType;

        Class caller = Util.getType(_typeName, dbinfo.getName(),
            dbinfo.getPackage(), dbinfo.getImports());
        // Verifica se e uma classe interna
        if(caller == null) {
            StringTokenizer tk = new StringTokenizer(_typeName, ".");
            if(tk.countTokens() > 1) {
                StringBuffer buf = new StringBuffer();
                int count = tk.countTokens() - 2;
                for(int k = 0;k < count;k++) {
                   buf.append(tk.nextToken() + ".");
                }
                buf.append(tk.nextToken() + "$" + tk.nextToken());
                _typeName = buf.toString();

                caller = Util.getType(_typeName, dbinfo.getName(),
                    dbinfo.getPackage(), dbinfo.getImports());
            }
        }

        // Testa para ver se acha os tipos no resto da hierarquia
        if(caller == null) {
            ClassData cd = dbinfo.getSuperClass();
            while(cd != null) {
                caller = Util.getType(_typeName, cd.getName(), 
                    cd.getPackage(), cd.getImports());

                if(caller != null) break;
                cd = cd.getSuperClass();
            }
        }

        // ve se e inner
        ClassData inner = dbinfo.getInnerClass(
            Util.innerClassName(caller.getName()));

        // adiciona a lista de parametros o tipo da classe pai
        if(inner != null) {
            Class type;
            if(dbinfo.isInner()) {
                type  = Util.getType(Util.innerClassLoader(dbinfo.getName()), dbinfo.getName(),
                    dbinfo.getPackage(), dbinfo.getImports());
            }
            else {
                 type = Util.getType(dbinfo.getName(), dbinfo.getName(), dbinfo.getPackage(), 
                     dbinfo.getImports());
            }
            _parameterTypes.addFirst(type);
        }
        _constructor = Util.getConstructor(caller, _parameterTypes);
    }
    
    ///////////////////////////////////////////////////////////////////
    ////                        public methods                     ////
    
    ///////////////////////////////////////////////////////////////////
    ////                      private variables                    ////

    private VarDefStatementInfo _vardef;

    private Constructor _constructor;

    private String _typeName;
    private LinkedList _parameterTypes;
}
